using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
using Unity.LEGO.Minifig;
using UnityEngine.SceneManagement;

using SLua;

[CustomLuaClass]
public class GameManager : MonoBehaviour
{
    private string[] m_Avatars = new string[] {
        "Adventurer",
        "Astronaut",
        "Pirate",
        "Pizza Boy"
    };


    private string[] m_SceneNames = new string[] {
        "Playground",
    };


    private Dictionary<int, GameObject> m_Players = new Dictionary<int, GameObject>();
    private int m_CurrentPlayerId = -1;
    private int m_CurrentSceneId = -1;

    private LuaSvr m_LuaSvr;
    private LuaTable m_LuaSelf;
    private LuaFunction m_LuaUpdate;
    private LuaFunction m_LuaLogin;
    private LuaFunction m_LuaLogout;
    private LuaFunction m_LuaGetPlayerList;

    private bool m_SceneLoaded;


    private static GameManager m_Instance;

    public static GameManager Instance
    {
        get
        {
            if (m_Instance == null)
            {
                GameObject go = new GameObject("GameMgrGO");
                DontDestroyOnLoad(go);
                m_Instance = go.AddComponent<GameManager>();
            }
            return m_Instance;
        }
    }


    void Awake()
    {
        m_LuaSvr = new LuaSvr();

        m_LuaSvr.init(null, () =>
        {
            m_LuaSelf = (LuaTable)m_LuaSvr.start("network");
            m_LuaUpdate = (LuaFunction)m_LuaSelf["update"];
            m_LuaLogin = (LuaFunction)m_LuaSelf["login"];
            m_LuaLogout = (LuaFunction)m_LuaSelf["logout"];
            m_LuaGetPlayerList = (LuaFunction)m_LuaSelf["get_player_list"];
        });

        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    public void RemovePlayer(int id)
    {
        Debug.LogFormat("RemovePlayer:{0}", id);

        if (m_Players.ContainsKey(id))
        {
            var player = m_Players[id];
            m_Players.Remove(id);
            GameObject.Destroy(player);
        }
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        Debug.Log("OnSceneLoaded: " + scene.name);
        m_SceneLoaded = true;
    }

    public bool IsSceneLoaded(int sceneId)
    {
        return m_CurrentSceneId == sceneId && m_SceneLoaded;
    }

    public void LoadScene(int sceneId)
    {
        if (m_CurrentSceneId != sceneId)
        {
            m_SceneLoaded = false;
            sceneId = sceneId % m_SceneNames.Length;
            SceneManager.LoadScene(m_SceneNames[sceneId], LoadSceneMode.Single);
            m_CurrentSceneId = sceneId;
        }
    }


    public void BindPlayer(int id)
    {
        if (m_Players.ContainsKey(id))
        {
            Debug.LogFormat("set main camera");

            var player = m_Players[id];
            var controller = player.GetComponent<MinifigController>();
            controller.SetInputEnabled(true);
            var camera = GameObject.Find("Main Camera");
            var freeLook = camera.GetComponent<CinemachineFreeLook>();
            freeLook.Follow = player.transform;
            freeLook.LookAt = player.transform;
        }
    }


    public void CreatePlayer(int id, string name, int avatar, float x, float y, float z)
    {
        Debug.Log("create player.....");
        if (!m_Players.ContainsKey(id))
        {
            Vector3 pos = new Vector3(x, y, z);
            avatar = avatar % m_Avatars.Length;
            var prefab = Resources.Load(m_Avatars[avatar]) as GameObject;
            var player = GameObject.Instantiate(prefab, pos, Quaternion.identity);
            m_Players.Add(id, player);
        }

    }

    public void Login(string user, string passwd)
    {
        m_LuaLogin.call(m_LuaSelf, user, passwd);
    }

    public void SetCurrentPlayer(int id)
    {
        m_CurrentPlayerId = id;
    }


    public void Logout(int id)
    {
        m_LuaLogin.call(m_LuaSelf, id);
    }

    public void GetPlayerList(){
        m_LuaGetPlayerList.call(m_LuaSelf, 1);
    }
    


    void Update()
    {
        m_LuaUpdate.call(m_LuaSelf);
    }
}
